package com.bubbleby.social.launch.client;

import java.util.Date;

import com.bubbleby.social.launch.client.external.ExternalJavascriptSuccessFailedCallback;
import com.bubbleby.social.launch.client.external.FacebookWrapper;
import com.bubbleby.social.launch.shared.FieldVerifier;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.http.client.URL;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Frame;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

/**
 * The UI Binder Class containing the complete Launch Page
 */
public class LaunchPage extends Composite {

	/** The ui binder. */
	private static LaunchPageUiBinder uiBinder = GWT.create(LaunchPageUiBinder.class);
	
	/** The 'unique' hash for the user. */
	private String hash = SocialLaunch.createAccessKey();
	
	/** The referral link forwarded to friends and followers. */
	private String referralLink = SocialLaunch.constants.siteURL() + "?r=" + hash;;
	
	/** The _registration service. */
	private RegisterServiceAsync _registerService;
	
	/** The IFrame holding the tweet button. */
	private Frame twitterFrame;
	
	/**
	 * The Interface LaunchPageUiBinder.
	 */
	interface LaunchPageUiBinder extends UiBinder<Widget, LaunchPage> {
	}

	/** The send email button. */
	@UiField
	HTML sendButton;
	
	/** The back link deleting the cookie. */
	@UiField
	InlineLabel back;

	/** The facebook button. */
	@UiField
	HTML facebookButton;

	/** The external buttons holder. */
	@UiField
	HTMLPanel externalButtonsHolder;

	/** The referral area switched on after email was successfully submitted. */
	@UiField
	FlowPanel referArea;
	
	/** The email input area shown initially. */
	@UiField
	FlowPanel inputArea;
	
	/** The rotating loader image at bottom right */
	@UiField
	FlowPanel loaderImage;
	
	/** The holder of the floating box*/
	@UiField
	FlowPanel boxHolder;
	
	/** The holder of the background image*/
	@UiField
	FlowPanel backgroundHolder;
	
	/** The email field. */
	@UiField
	TextBox emailField;

	/** The background image. */
	@UiField
	Image backgroundImage;

	/** The mailto: button. */
	@UiField
	Anchor mailButton;

	/** The error label of the email field. */
	@UiField
	Label errorLabel;
	

	/**
	 * Instantiates the launch page.
	 */
	public LaunchPage(RegisterServiceAsync registerService) {

		this._registerService = registerService;
		
		String parameter = Window.Location.getParameter("r");
		if (parameter != null)
			SocialLaunch.trackEventInAnalytics("Referral", "Initiated", parameter);

		initWidget(uiBinder.createAndBindUi(this));
		loaderImage.setVisible(false);
		changeBgImage(Window.getClientWidth(), Window.getClientHeight(), false);
		
		//check whether email was already submitted and hash exists
		if (getCookie() != null && !getCookie().trim().isEmpty()) {
			inputArea.setVisible(false);
			hash = getCookie();
			referralLink = SocialLaunch.constants.siteURL() + "?r=" + hash;
		} else
			referArea.setVisible(false);

		externalButtonsHolder.add(getTwitterFrame(referralLink));
		mailButton.setHref(SocialLaunch.messages.mailtoMessage(referralLink));
		
		//Set a different margin for Phones (Ok, it's a bit of a hack)
		if (Window.getClientWidth() < 500)
			boxHolder.getElement().getStyle().setMarginTop(20, Unit.PX);
		
		emailField.setText(SocialLaunch.constants.defaultMail());
		emailField.setFocus(true);
		emailField.selectAll();

		
		
	}

	/**
	 * Gets the twitter frame.
	 *
	 * @return the twitter frame
	 */
	private Frame getTwitterFrame(String referralLink) {
		if (twitterFrame==null) {
			twitterFrame = new Frame("http://platform.twitter.com/widgets/tweet_button.html?url=" + URL.encodeQueryString(referralLink) + "&count=none&text=" + URL.encode(SocialLaunch.messages.defaultTwitterMessage()) + "&via="
					+ SocialLaunch.constants.twitterAccount() + "&lang=en");
			twitterFrame.getElement().setAttribute("allowtransparency", "true");
			twitterFrame.setWidth("55px");
			twitterFrame.setHeight("20px");
			twitterFrame.getElement().setAttribute("scrolling", "no");
			twitterFrame.getElement().setAttribute("frameBorder", "0");
			twitterFrame.setStyleName(SocialLaunch.resourceBundle.generalCSS().twitter());
		}
		return twitterFrame;
	}

	/**
	 * On Click Handler of the send email button
	 *
	 * @param e the ClickEvent
	 */
	@UiHandler("sendButton")
	void onClickSend(ClickEvent e) {
		sendEmailToServer();
	}

	/**
	 * On Click Handler of Back Link
	 *
	 * @param e the ClickEvent
	 */
	@UiHandler("back")
	void onClickBack(ClickEvent e) {
		removeCookie();
		hash = SocialLaunch.createAccessKey();
		
		resetExternalButtons(hash);
		referArea.setVisible(false);
		inputArea.setVisible(true);
	}

	/**
	 * On click Handler of Facebook Button.
	 *
	 * @param e the ClickEvent
	 */
	@UiHandler("facebookButton")
	void onClickFacebook(ClickEvent e) {
		FacebookWrapper.facebookStreamPublishWithImage(SocialLaunch.messages.facebookMessage(referralLink), SocialLaunch.constants.facebookCaption(), SocialLaunch.constants.facebookHeaderLinkTitle(), referralLink, SocialLaunch.constants
				.facebookThumbnailURL(), new ExternalJavascriptSuccessFailedCallback() {

			@Override
			public void onSuccess() {
				
			}

			@Override
			public void onFailure() {
			
			}
		});
	}

	/**
	 * On key up of email field
	 *
	 * @param event the KeyUpEvent
	 */
	@UiHandler("emailField")
	void onKeyUp(KeyUpEvent event) {
		if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
			emailField.setFocus(false);
			sendEmailToServer();
		}
	}

	/**
	 * On focus of email field.
	 *
	 * @param e the FocusEvent
	 */
	@UiHandler("emailField")
	void onFocusEmailField(FocusEvent e) {
		emailField.getElement().getStyle().setColor("#556270");
		if (emailField.getText().trim().equalsIgnoreCase(SocialLaunch.constants.defaultMail()))
			emailField.setText("");
	}

	/**
	 * On blur of email field
	 *
	 * @param e the BlurEvent
	 */
	@UiHandler("emailField")
	void onBlurEmailField(BlurEvent e) {
		if (emailField.getText().trim().isEmpty()) {
			emailField.setText(SocialLaunch.constants.defaultMail());
			emailField.getElement().getStyle().clearColor();
		}
	}

	/**
	 * Sets the error label.
	 *
	 * @param text the new error label text
	 */
	public void setErrorLabel(String text) {
		errorLabel.setText(text);
	}

	/**
	 * Gets the email field value
	 *
	 * @return the email field value
	 */
	public String getEmailField() {
		return emailField.getText();
	}

	/**
	 * Send the email from the emailField to the server and wait for a response.
	 */
	private void sendEmailToServer() {
		
		String parameter = Window.Location.getParameter("r");
		if (parameter == null || parameter.trim() == "")
			parameter = "";
		else
			SocialLaunch.trackEventInAnalytics("Referral", "Success", parameter);

		setErrorLabel(" ");
		String email = getEmailField();
		if (email.equalsIgnoreCase(SocialLaunch.constants.defaultMail()))
			return;

		if (!FieldVerifier.isValidEmail(email)) {
			setErrorLabel(SocialLaunch.constants.errorEmailFormat());
			return;
		}
		loaderImage.setVisible(true);
	
		_registerService.registerServer(email, parameter, hash, new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				errorLabel.setText(caught.getMessage());
				loaderImage.setVisible(false);
			}

			public void onSuccess(String result) {
				if (!result.equals(hash)) {
					//user already has a hash
					hash = result;
					resetExternalButtons(hash);
				} else {
					String parameter = Window.Location.getParameter("r");
					SocialLaunch.trackEventInAnalytics("Email", "added", getEmailField(), (parameter==null) ? "no parameter" : parameter);
				}
				setCookie(hash);
				
				loaderImage.setVisible(false);
				referArea.setVisible(true);
				inputArea.setVisible(false);
			}

		
		});
	
	}

	private void resetExternalButtons(String hash) {
		referralLink = SocialLaunch.constants.siteURL() + "?r=" + hash;
		if (twitterFrame!=null)
			twitterFrame.removeFromParent();
		twitterFrame=null;
		externalButtonsHolder.add(getTwitterFrame(referralLink));
		mailButton.setHref(SocialLaunch.messages.mailtoMessage(referralLink));
	}
	
	/**
	 * Change background image size to fit viewport
	 *
	 * @param viewportX the viewport x
	 * @param viewportY the viewport y
	 * @param center the center
	 */
	public void changeBgImage(double viewportX, double viewportY, boolean center) {
		    if (viewportY < SocialLaunch.constants.minImageHeight()) {
		    	viewportY=SocialLaunch.constants.minImageHeight();
		    	backgroundHolder.getElement().getStyle().setHeight(SocialLaunch.constants.minImageHeight(), Unit.PX);
		    } else {
		    	backgroundHolder.getElement().getStyle().clearHeight();
		    }
		    double imageRatio = SocialLaunch.constants.imageWidth() / SocialLaunch.constants.imageHeight(); 
			if ( imageRatio <= viewportX / viewportY) {
				backgroundImage.getElement().getStyle().setWidth(viewportX, Unit.PX);
				backgroundImage.getElement().getStyle().setHeight(viewportX/imageRatio, Unit.PX);
				if (center)
					backgroundImage.getElement().getStyle().clearMarginLeft();
			} else {
				backgroundImage.getElement().getStyle().setHeight(viewportY, Unit.PX);
				backgroundImage.getElement().getStyle().setWidth(viewportY*imageRatio, Unit.PX);
				if (center)
					backgroundImage.getElement().getStyle().setMarginLeft((viewportX - (SocialLaunch.constants.imageWidth() * (viewportY / SocialLaunch.constants.imageHeight()))) / 2, Unit.PX);
				
			}
		

	}

	/**
	 * Sets the hash cookie to allow the user to come back and send out with the same hash.
	 *
	 * @param hash the new cookie hash
	 */
	public void setCookie(String hash) {
		Cookies.setCookie("hash", hash, new Date(System.currentTimeMillis() + 31536000000L));
	}

	/**
	 * Gets the hash from the cookie
	 *
	 * @return the cookie hash
	 */
	public String getCookie() {
		return Cookies.getCookie("hash");
	}

	/**
	 * Removes the hash cookie.
	 */
	public void removeCookie() {
		Cookies.removeCookie("hash");
	}


}
